import { Asset, assetManager, Constructor, __private } from "cc";
import { bundleManager } from "../bundleManager/BundleManager";


type ProgressCallback = ((finished: number, total: number, item: any) => void);
type CompleteCallback<T extends Asset> = (err: Error | null, data: T) => void ;
type IRemoteOptions =  { [k: string]: any, ext?: string };
type AssetType<T = Asset> = Constructor<T>;

/**
 * 资源管理类
 * 1. 加载远程资源
 * 2. 加载本地资源
 * 3. 释放资源包中的资源
 */
class ResMananger {
    private static _instance: ResMananger = null;
    public static get instance(): ResMananger {
        if (this._instance == null) {
            this._instance = new ResMananger();
        }
        return this._instance;
    }
   
    /**
     * 加载远程资源
     * @param url 资源地址
     * @param options  资源参数，例：{ ext: ".png" }
     * @param onComplete 加载完成回调
     * @example
        resMananger.loadRemote('http://www.cloud.com/test1.jpg', (err, texture) => console.log(err));
        resMananger.loadRemote('http://www.cloud.com/test2.mp3', (err, audioClip) => console.log(err));
        resMananger.loadRemote('http://www.cloud.com/test3', { ext: '.png' }, (err, texture) => console.log(err));
     */
    public loadRemote<T extends Asset> (url: string, options: IRemoteOptions | null, onComplete?: CompleteCallback<T> | null);
    public loadRemote<T extends Asset> (url: string, onComplete?: CompleteCallback<T> | null);
    public loadRemote<T extends Asset> (url: string, options?: IRemoteOptions | CompleteCallback<T> | null, onComplete?: CompleteCallback<T> | null) {
        if (typeof options === "function") {
            onComplete = options;
            options = null;
        }
        assetManager.loadRemote(url, options, onComplete);
    }

    /**
     * 加载资源
     * @param bundleName 资源包名称
     * @param path 资源路径
     * @param onComplete 加载完成回调
     * @param onProgress 加载进度回调
     */
    public load<T extends Asset>(bundleName: string, path: string, onComplete: CompleteCallback<T>, onProgress: ProgressCallback = null) {
        const bundle = bundleManager.getBundle(bundleName)
        bundle.load<T>(path, onProgress, onComplete);
    }


    /**
     * 加载本地资源
     * @param bundleName  资源包名称
     * @param path  资源路径
     * @param onProgress  加载进度回调
     * @returns 资源
     */
    public async loadAsync<T extends Asset>(bundleName: string, path: string, onProgress: ProgressCallback = null): Promise<T> {
        return new Promise<T>((resolve, reject) => {
            const bundle = bundleManager.getBundle(bundleName)
            bundle.load<T>(path, onProgress, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            })
        });
    }

    /** 打印缓存中所有资源信息 */
    public dump() {
        assetManager.assets.forEach((value: Asset, key: string) => {
            console.log("asset key:", key);
            console.log(assetManager.assets.get(key));
        })
        console.log(`当前资源总数:${assetManager.assets.count}`);
    }
}



/** 资源管理 */
export const resMananger = ResMananger.instance;